﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Data;

namespace PhantomMvvmToolkit.Converter
{
    /// <summary>
    /// This will convert a boolean value, numeric value, or a string value of the Visibility enum, or "".  It will also accept any of those types as nullable
    /// </summary> 
    /// <remarks>
    /// bool: true = Visible, false = Collapsed
    /// int, float, double: 0 = Collapsed, anything else Visible
    /// string: "" = Collapsed otherwise it will try to enum parse
    /// null: Collapsed
    /// Default: Visible if not a convertable type (one way)
    /// 
    /// Adding a parameter of "Inverse" will cause all results to be reversed
    /// </remarks>
    /// <exception cref="InvalidOperationException"></exception>
    public class ToVisibility : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            var inverse = false;
            var result = Visibility.Collapsed;

            if (parameter != null && parameter.ToString().ToLower() == "inverse")
            {
                inverse = true;
            }

            if (value is bool)
            {
                result = (bool)value ? Visibility.Visible: Visibility.Collapsed;
            }
            else if (value is int)
            {
                result = (int)value == 0 ? Visibility.Collapsed : Visibility.Visible;
            }
            else if (value is float)
            {
                result = (float)value == 0 ? Visibility.Collapsed : Visibility.Visible;
            }
            else if (value is double)
            {
                result = (double)value == 0 ? Visibility.Collapsed : Visibility.Visible;
            }
            else if (value is string)
            {
                if (string.IsNullOrEmpty((string)value))
                    result = Visibility.Collapsed;

                try
                {
                    result = (Visibility)Enum.Parse(typeof(Visibility), (string)value, true);
                }
                catch 
                {
                    throw new InvalidOperationException(string.Format("Type is string but it did not convert to a valid Visibility enum.  It's value was {0}", value));
                }
            }
            else if (value == null)
            {
                result = Visibility.Collapsed;
            }
            else
            {
                result = Visibility.Visible;
            }

            if (inverse)
            {
                switch (result)
                {
                    case Visibility.Collapsed:
                        return Visibility.Visible;
                    case Visibility.Visible:
                        return Visibility.Collapsed;
                    default:
                        return result;
                }
            }
            else
                return result;
        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            var current = (Visibility)value;

            if (parameter.ToString().ToLower() == "inverse")
            {
                switch (current)
                {
                    case Visibility.Collapsed:
                        current = Visibility.Visible;
                        break;
                    case Visibility.Visible:
                        current = Visibility.Collapsed;
                        break;
                }
            }

            if (targetType == typeof(bool) || targetType == typeof(bool?))
            {
                return current == Visibility.Visible;
            }

            if (targetType == typeof(int) || targetType == typeof(float) || targetType == typeof(double) ||
                targetType == typeof(int?) || targetType == typeof(float?) || targetType == typeof(double?))
            {
                return current == Visibility.Visible ? 1 : 0;
            }

            if (targetType == typeof(string))
            {
                return current == Visibility.Visible ? "Visible" : "Collapsed";
            }

            throw new InvalidOperationException(string.Format("Type {0} is not a valid conversion type for ConvertBack.", targetType.Name));
        }
    }
}
